/**
 * 
 */
package rs.fon.rapidminer.operator.learner.tree;

import rs.fon.rapidminer.process.annotation.Parameter;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.learner.tree.DecisionTreeLeafCreator;
import com.rapidminer.operator.learner.tree.LeafCreator;
import com.rapidminer.operator.learner.tree.Terminator;
import com.rapidminer.operator.learner.tree.Tree;
import rs.fon.rapidminer.operator.learner.tree.SplittedExampleSet;
import java.util.LinkedList;
import com.rapidminer.example.Attribute;
import java.util.List;
import rs.fon.rapidminer.operator.learner.tree.FrequencyCalculator;

/**
 * @author Nikola
 * 
 */
public class GainRatioSplit extends AbstractSplit {
	

	Attribute bestAttribute;
	int bestAttributeInt;
	SplittedExampleSet bestSplitted;
	double bestBenefit = -1;
	private FrequencyCalculator calculator = new FrequencyCalculator();
	private InforamtionGainSplit infoGain = new InforamtionGainSplit();
	 private static double LOG_FACTOR = 1d / Math.log(2);
	
	@Override
	public Object DoWork(List<SplittedExampleSet> sviSplitedi, List<rs.fon.rapidminer.process.Parameter> parameters)
	{
		int i = 0;
		
		for(SplittedExampleSet ses : sviSplitedi)
		{
			i++;
			double currentBenefit = -1;
			
		    double[] partitionWeights = calculator.getPartitionWeights((SplittedExampleSet)ses.clone());
	        double totalWeight = calculator.getTotalWeight(partitionWeights);
	        
	        double gain = ((Double)infoGain.GetBenefit(ses)).doubleValue();
	        double splitInfo = getSplitInfo(partitionWeights, totalWeight);
	        if (splitInfo == 0)
	            currentBenefit = gain;
	        else
	            currentBenefit = gain / splitInfo;
	        
	        if(currentBenefit > bestBenefit)
			{
				bestBenefit = currentBenefit;
				bestSplitted = ses;
				bestAttribute = ses.getAttribute();
			}		
		}   	
	
		return bestSplitted;		
	}
	
	 protected double getSplitInfo(double[] partitionWeights, double totalWeight) {
	        double splitInfo = 0;
	        for (double partitionWeight : partitionWeights) {
	            if (partitionWeight > 0) {
	                double partitionProportion = partitionWeight / totalWeight;
	                splitInfo += partitionProportion * Math.log(partitionProportion) * LOG_FACTOR;
	            }
	        }
	        return -splitInfo;
	    }  
	 
	 @Override
	    public Object GetBenefit(SplittedExampleSet exampleSet) {
		 return null;
	 }
	
	  
	 @Override
		public Object GetBestAttribute(SplittedExampleSet exampleSet)
		{
			
			return bestAttribute;
		}
		
		@Override
		public Object GetBenefit()	
		{
			return bestBenefit;
		}
	
}